package org.refresh.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;


/*******************************************************************************
 * Copyright (c) 2005, 2006 Jules White. All rights reserved. This program and
 * the accompanying materials are made available under the terms of the Eclipse
 * Public License v1.0 which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: Jules White - initial API and implementation
 ******************************************************************************/
public class ParsingUtil {

	public static final String ARGS_SPLITTER = "[\\;\\=]";
	
	public static final String KEY_VALUE_SPLITTER = "=";

//	public static Map parseMap(String argstr) {
//		if (argstr != null) {
//			argstr = argstr.trim();
//			if (argstr.startsWith("[") && argstr.endsWith("]")) {
//				argstr = argstr.substring(1, argstr.length() - 1);
//			}
//			String[] argarray = argstr.split(ARGS_SPLITTER);
//			if (argarray.length % 2 != 0)
//				throw new ArgumentsFormatException(
//						"The arguments string:\""
//								+ argstr
//								+ "\" is not formatted properly. (hint: there is either a missing semicolon or equals sign)");
//			HashMap args = new HashMap(7);
//			for (int i = 0; i < argarray.length; i += 2) {
//				args.put(argarray[i].trim(), argarray[i + 1].trim());
//			}
//			return args;
//		}
//		return new HashMap();
//	}
	
	public static Map parseMap(String map){
		map = map.replaceAll("\\/\\*[^\\*]*[^\\/]*\\*\\/", "");
		return parseMap(new StringTokenizer(map,"{};[]"+KEY_VALUE_SPLITTER,true),false, "}");
	}
	
	public static Map parseSimpleMap(String map){
		return parseSimpleMap(map, "}");
	}
	
	public static Map parseSimpleMap(String map, String enddelim){
		map = map.replaceAll("\\/\\*[^\\*]*[^\\/]*\\*\\/", "");
		return parseMap(new StringTokenizer(map,"{};[]"+KEY_VALUE_SPLITTER,true),true, enddelim);
	}
	
	public static List parseList(String list){
		list = list.replaceAll("\\/\\*[^\\*]*[^\\/]*\\*\\/", "");
		return parseList(new StringTokenizer(list,"{},[]",true),false);
	}
	
	public static List parseFlatList(String list){
		list = list.replaceAll("\\/\\*[^\\*]*[^\\/]*\\*\\/", "");
		return parseList(new StringTokenizer(list,"{},[]",true),true);
	}
	
	public static List parseList(StringTokenizer tokens, boolean flat){
		tokens.nextToken();
		ArrayList list = new ArrayList(tokens.countTokens());
		String value = "";
		while(tokens.hasMoreTokens()){
			String token = tokens.nextToken();
			Object item = token;
			
			if(token.equals("]"))
				break;
			if(token.equals(",")){
				value = value.trim();
				if(value.startsWith("[") && value.endsWith("]") && !flat){
					item = parseList(value);
				}
				else if(value.startsWith("{") && value.endsWith("}") && !flat){
					item = parseMap(value);
				}
				else {
					item = value;
				}
				list.add(item);
				value = "";
				continue;
			}
			else if(token.equals("[")){
				token = "["+parseEscapedValue(tokens, "[","]");
			}
			else if(token.equals("{")){
				token = "{"+parseEscapedValue(tokens, "{", "}");
			}
			
			value += token;
			
		}
		if(value.trim().length() != 0){
			Object item = value;
			value = value.trim();
			if(value.startsWith("[") && value.endsWith("]") && !flat){
				item = parseList(value);
			}
			else if(value.startsWith("{") && value.endsWith("}") && !flat){
				item = parseMap(value);
			}
			
			list.add(item);
		}
		return list;
	}
	
	public static Map parseMap(StringTokenizer style, boolean simple, String enddelim){
		style.nextToken();
		
		boolean inval = false;
		String token = null;
		String key = null;
		HashMap props = new HashMap();
		String value = "";
		while(style.hasMoreTokens()){
			
			token = style.nextToken();
			
			token = token.trim();
			if(token.length() < 1)
				continue;
			
			if(token.equals(enddelim)){
				if(inval && (value == null || value.trim().length()==0))
					throw new ArgumentsFormatException(
								"The arguments string is not formatted properly. (hint: there is either a missing semicolon or equals sign)");
				if(inval){
					if(value.startsWith("[") && value.endsWith("]") && !simple)
						props.put(key, parseList(value));
					else if(value.startsWith("{") && value.endsWith("}") && !simple)
						props.put(key, parseMap(value));
					else
						props.put(key,value.trim());
				}
				break;
			}
			if(token.equals(KEY_VALUE_SPLITTER))
				inval = true;
			if(token.equals(";") && (value == null || value.trim().length()==0))
				throw new ArgumentsFormatException(
						"The arguments string is not formatted properly. (hint: there is either a missing semicolon or equals sign)");
			if(token.equals(";")){
				inval = false;
				value = value.trim();
				if(value.startsWith("[") && value.endsWith("]") && !simple)
					props.put(key, parseList(value));
				else if(value.startsWith("{") && value.endsWith("}") && !simple)
					props.put(key, parseMap(value));
				else
					props.put(key,value);

				value = "";
				key = null;
			}
			if(token.equals("{") && inval)
				token = "{"+parseEscapedValue(style,"{","}");
			if(token.equals("["))
				token = "["+parseEscapedValue(style, "[","]");
			if(!token.equals(";")
					&& !token.equals(KEY_VALUE_SPLITTER)){
				if(key == null){
					key = token.trim();
				}
				else{
					value += token;
				}
			}
			
		}
		
		return props;
	}
	
	public static String parseEscapedValue(StringTokenizer tk, String startdelim, String enddelim){
		int lhs = 1;
		
		String val = "";
		while(lhs > 0 && tk.hasMoreTokens()){
			String token = tk.nextToken();
			if(token.equals(startdelim)){
				lhs++;
				val += startdelim;
			}
			else if(token.equals(enddelim)){
				lhs--;
				val += enddelim;
			}
			else
				val += token;
		}
		return val;
	}
	
}
